package com.gator.spring.framework.aop.aspect;

import java.lang.reflect.Method;

/**
 * @Authror PABLO
 * @Date 2022/5/8 17:15
 * @Desc 抽象通知接口实现
 */
public abstract class PABLO_AbstractAspectAdvice {
    //切面方法  如before after...
    private Method aspectMethod;
    //切面所在的类 如自定义的LogAspect
    private Object aspectTarget;

    public PABLO_AbstractAspectAdvice(Method aspectMethod, Object aspectTarget) {
        this.aspectMethod = aspectMethod;
        this.aspectTarget = aspectTarget;
    }

    /**
     * @Description:
     * @Author: PABLO
     * @Date: 2022/5/9 23:42
     * @Params: [joinPoint连接点, returnValue返回值, tx异常信息]
     * @Return: java.lang.Object
     **/
    //被每个通知（拦截器链节点）调用
    public Object invokeAdviceMethod(PABLO_JoinPoint joinPoint, Object returnValue, Throwable tx) throws Throwable {
        //获得切面方法的参数列表
        Class<?>[] paramTypes = this.aspectMethod.getParameterTypes();
        //如参数直接反射调用
        if (null == paramTypes || paramTypes.length == 0) {
            return this.aspectMethod.invoke(aspectTarget);
        } else {
            //有参数，匹配这三个入参
            Object[] args = new Object[paramTypes.length];
            for (int i = 0; i < paramTypes.length; i++) {
                if (paramTypes[i] == PABLO_JoinPoint.class) {
                    args[i] = joinPoint;
                } else if (paramTypes[i] == Throwable.class) {
                    args[i] = tx;
                } else if (paramTypes[i] == Object.class) {
                    args[i] = returnValue;
                }
            }//根据aspectMethod确定是哪一个通知，调用该通知的具体方法，如before，这里会调用before的
            //com.gator.spring.executor.aspect.LogAspect.before
            return this.aspectMethod.invoke(aspectTarget, args);
        }
    }
}
